package com.ydy.ewallet.config;

import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.ydy.ewallet.enums.ErrorEnums;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.*;

/**
 * 全局异常处理器
 *
 * @author Kephon
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 适用参数校验抛出异常
     */
    @ExceptionHandler(value = ApiException.class)
    public R<Object> handleApiException(ApiException e) {
        log.warn("{}", e.getLocalizedMessage());
        return R.failed(e.getLocalizedMessage());
    }

    /**
     * 参数绑定异常
     */
    @ExceptionHandler(value = BindException.class)
    public R<Object> handleBindException(BindException e) {
        List<Object> jsonList = new ArrayList<>();
        e.getBindingResult().getFieldErrors().forEach(fieldError -> {
            Map<String, Object> jsonObject = new HashMap<>(2);
            jsonObject.put("name", fieldError.getField());
            jsonObject.put("msg", fieldError.getDefaultMessage());
            jsonList.add(jsonObject);
        });
        log.warn("{}", Arrays.toString(jsonList.toArray()));
        return R.restResult(jsonList, ApiErrorCode.FAILED);
    }

    /**
     * 400 - Bad Request
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.warn("请求参数错误: {}", e.getLocalizedMessage());
        return R.failed("请求参数错误");
    }

    /**
     * 405 - Method Not Allowed
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R<Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.warn("请求方式不受支持: {}", e.getLocalizedMessage());
        return R.failed("请求方式不受支持: " + e.getMethod());
    }

    /**
     * 415 - Unsupported Media Type
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public R<Object> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        log.warn("content-type不受支持: {}", e.getLocalizedMessage());
        return R.failed("content-type不受支持: " + e.getContentType());
    }

    /**
     * 缺少参数错误
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public R<Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        return R.failed("缺少参数: " + e.getParameterName());
    }

    /**
     * 全局异常
     */
    @ExceptionHandler(value = Exception.class)
    public R<Object> handleException(Exception e) {
        e.printStackTrace();
        log.error("错误信息: {}", e.getLocalizedMessage(), e);
        return R.failed(ErrorEnums.INTERNAL_SERVER_ERROR.getMsg());
    }

}
